package client_service

/**
* @author aFun
* @data 2025/4/12 12:33
* @email: afunaaa222@163.com / 1030935903
* @address: Guangdong University of Technology, China
 */

import (
	"camp_lucky_draw/entity"
	"camp_lucky_draw/transfer"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"strconv"
	"text/tabwriter"
	"time"
)

//var srMutex = sync.Mutex{}

// 封装发送与接收
func Send_and_receive(mes *entity.Msg) (respMes *entity.Msg, err error) {
	//// 控制一条TCP连接请求只能发送一次数据，不然在上一条数据没到来回复前就又发一条，会引起TCP粘包问题
	//srMutex.Lock()
	//defer srMutex.Unlock()
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()
	respChan := RespChannelMap[mes.Code]
	if mes == nil {
		return &entity.Msg{
			Code:    0,
			Status:  false,
			Message: "mes is nil",
		}, fmt.Errorf("请求体为nil failed: %w", err)
	}
	data, err := json.Marshal(mes)
	if err != nil {
		return
	}
	tf := &transfer.Transfer{
		Conn: CurUser.Conn,
	}
	err = tf.WritePkg(data)
	if err != nil {
		return
	}

	select {
	case respMes = <-respChan:
		return respMes, nil
	case <-ctx.Done():
		// 超时后清理
		go func() {
			select {
			case <-respChan:
			default:
			}
		}()
		return nil, errors.New("响应超时")
	}
}

// 客户端打印层奖励数据
func Pretty_print_floor_reward_table(data string) {
	return
	var rewards []entity.Client_floor_reward
	err := json.Unmarshal([]byte(data), &rewards)
	if err != nil {
		fmt.Println("解析失败:", err)
		return
	}

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "层数\t位置\t物品名\t数量\t最大数量")
	fmt.Fprintln(w, "----\t----\t------\t----\t--------")

	for _, r := range rewards {
		fmt.Fprintf(w, "%d\t%d\t%s\t%d\t%d\n", r.Floor, r.Pos, r.ItemName, r.Quantity, r.MaxQuantity)
	}

	w.Flush()
}

// 客户端打印累计奖励数据
func Pretty_print_cumulative_reward_table(data string) {
	return
	var rewards []entity.Client_cumulative_reward
	err := json.Unmarshal([]byte(data), &rewards)
	if err != nil {
		fmt.Println("解析失败:", err)
		return
	}

	// 创建表格输出格式
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "消耗Token\t物品名\t数量")
	fmt.Fprintln(w, "----------\t------\t----")

	// 遍历每个奖励项，按表格格式输出
	for _, r := range rewards {
		fmt.Fprintf(w, "%d\t%s\t%d\n", r.TokenCost, r.ItemName, r.Quantity)
	}

	w.Flush()
}

// 客户端打印扭蛋信息数据
func PrettyPrintUserStatus(data string) {
	return
	var luckydraw entity.LuckyDraw
	err := json.Unmarshal([]byte(data), &luckydraw)
	if err != nil {
		fmt.Println("解析失败:", err)
		return
	}

	// 创建表格输出格式
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "ID\t角色ID\t层变化\t当前层\t消耗Token\t抽奖次数\t奖励状态\t结束状态")
	fmt.Fprintln(w, "---\t------\t------\t------\t---------\t-------\t--------\t--------")

	// 格式化并打印表格数据
	fmt.Fprintf(w, "%d\t%d\t%d\t%d\t%d\t%v\t%v\n",
		luckydraw.ID,
		luckydraw.Role_id,
		luckydraw.Prev_change,
		luckydraw.Cur_floor,
		luckydraw.Consumed_tokens,
		luckydraw.Draw_num,
		luckydraw.Is_end)
	w.Flush()
}

// 查看个人信息
func Eoutput_self_lucky_draw_data() (err error) {
	if CurUser.Role.Lucky_draw.Role_id == CurUser.Role.ID {
		return nil
		fmt.Println("从本地数据读取。。。")
		luckydraw := CurUser.Role.Lucky_draw
		// 创建表格输出格式
		w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
		fmt.Fprintln(w, "ID\t角色ID\t层变化\t当前层\t消耗Token\t抽奖次数\t奖励状态\t结束状态")
		fmt.Fprintln(w, "---\t------\t------\t------\t---------\t-------\t--------\t--------")

		// 格式化并打印表格数据
		fmt.Fprintf(w, "%d\t%d\t%d\t%d\t%d\t%v\t%v\n",
			luckydraw.ID,
			luckydraw.Role_id,
			luckydraw.Prev_change,
			luckydraw.Cur_floor,
			luckydraw.Consumed_tokens,
			luckydraw.Draw_num,
			luckydraw.Is_end)
		w.Flush()
		return nil
	}

	var mes = &entity.Msg{
		Code: 27100,
		// 事实上UserId都不用传。。。server那边会保留Conn对应的UserId的。。懒得改
		Request_data: strconv.Itoa(int(CurUser.Role.ID)),
	}
	Resp, err := Send_and_receive(mes)
	if err != nil {
		return
	}
	if !Resp.Status {
		errStr := "网络请求失败，原因：" + Resp.Message
		err = errors.New(errStr)
		return
	}
	//PrettyPrintUserStatus(Resp.Repsonse_data)
	return nil
}

// 查看层奖励信息
func Eoutput_floor_lucky_draw_data() (err error) {
	cacheKey := fmt.Sprintf("floor_rewawrds_user_%d", CurUser.Role.ID)

	// 看本地缓存是否有数据
	if cachedData, found := globalCache.Get(cacheKey); found {
		//fmt.Println("从本地缓存中获取数据...")
		Pretty_print_floor_reward_table(cachedData.(string))
		return nil
	}

	var mes = &entity.Msg{
		Code: 27101,
		// 事实上UserId都不用传。。。server那边会保留Conn对应的UserId的。。懒得改
		Request_data: strconv.Itoa(int(CurUser.Role.ID)),
	}
	Resp, err := Send_and_receive(mes)
	if err != nil {
		return
	}
	if !Resp.Status {
		errStr := "网络请求失败，原因：" + Resp.Message
		err = errors.New(errStr)
		return
	}
	//fmt.Println("从网络获取数据，存入本地数据...")
	globalCache.Set(cacheKey, Resp.Repsonse_data, time.Minute*1)
	//Pretty_print_floor_reward_table(Resp.Repsonse_data)
	return nil
}

// 查看累计奖励信息
func Eoutput_cumulative_lucky_draw_data() (err error) {
	cacheKey := fmt.Sprintf("cumulative_rewawrds_user_%d", CurUser.Role.ID)

	// 看本地缓存是否有数据
	if cachedData, found := globalCache.Get(cacheKey); found {
		//fmt.Println("从本地缓存中获取数据...")
		Pretty_print_cumulative_reward_table(cachedData.(string))
		return nil
	}

	var mes = &entity.Msg{
		Code: 27102,
		// 事实上UserId都不用传。。。server那边会保留Conn对应的UserId的。。懒得改
		Request_data: strconv.Itoa(int(CurUser.Role.ID)),
	}
	Resp, err := Send_and_receive(mes)
	if err != nil {
		return
	}
	if !Resp.Status {
		errStr := "网络请求失败，原因：" + Resp.Message
		err = errors.New(errStr)
		return
	}
	//fmt.Println("从网络获取数据，存入本地数据...")
	globalCache.Set(cacheKey, Resp.Repsonse_data, time.Minute*1)
	//Pretty_print_cumulative_reward_table(Resp.Repsonse_data)
	return nil
}

// 扭蛋
func Edraw(IsProtected bool) (err error) {
	var mes = &entity.Msg{
		Code:         27103,
		Request_data: strconv.FormatBool(IsProtected),
	}
	Resp, err := Send_and_receive(mes)
	if err != nil {
		return
	}
	if Resp.Message != "" {
		//fmt.Println("扭蛋失败，原因：", Resp.Message)
	} else {
		//fmt.Println("扭蛋成功！")
	}

	//if !Resp.Status {
	//	errStr := "网络请求失败，原因：" + Resp.Message
	//	err = errors.New(errStr)
	//	return
	//} else {
	//	err = Eoutput_self_lucky_draw_data()
	//	if err != nil {
	//		return err
	//	}
	//}
	return nil
}

// 领取层奖励
func Eget_floor_reward(floor, pos int8) (err error) {
	var fr = &entity.Client_floor_reward{
		Floor: floor,
		Pos:   pos,
	}
	data, err := json.Marshal(fr)
	if err != nil {
		return err
	}
	var mes = &entity.Msg{
		Code:         27104,
		Request_data: string(data),
	}
	Resp, err := Send_and_receive(mes)
	if err != nil {
		return
	}
	// 理论上是应该判断这个Status，但为了压测
	//if !Resp.Status {
	//	errStr := "网络请求失败，原因：" + Resp.Message
	//	err = errors.New(errStr)
	//	return
	//}
	if Resp.Message != "" {
		//fmt.Println("层奖励领取失败，原因：", Resp.Message)
	} else {
		//fmt.Println("层奖励领取成功！")
	}
	return nil
}

// 领取累计奖励
func Eget_cumulative_reward(cumlativeLst []int64) (err error) {
	data, err := json.Marshal(cumlativeLst)
	if err != nil {
		return err
	}
	var mes = &entity.Msg{
		Code:         27105,
		Request_data: string(data),
	}
	Resp, err := Send_and_receive(mes)
	if err != nil {
		return
	}
	//if !Resp.Status {
	//	errStr := "网络请求失败，原因：" + Resp.Message
	//	err = errors.New(errStr)
	//	return
	//}
	//fmt.Println("累计奖励领取成功！")
	if Resp.Message != "" {
		//fmt.Println("累计奖励领取失败，原因：", Resp.Message)
	} else {
		//fmt.Println("累计奖励领取成功！")
	}
	return nil
}

// 断开连接
func Logout() (err error) {
	var mes = &entity.Msg{
		Code: 10002,
	}
	Resp, err := Send_and_receive(mes)
	if err != nil {
		return err
	}
	if !Resp.Status {
		errStr := "网络请求失败：" + Resp.Message
		err = errors.New(errStr)
		return err
	}
	return nil
}
